"""
L16设备控制器
L16 Device Controller

L16智能手环设备的主要控制逻辑
Main control logic for L16 smart wristband device
"""

import logging
import asyncio
from typing import Dict, Any, Optional, List
from datetime import datetime, timedelta

from ..base import BaseDevice
from .protocol import L16Protocol
from .models import L16DataModels

# 导入业务逻辑处理函数 / Import business logic handler functions
from service.l16_handler import handle_health, handle_warning
from service.location import location_handle_new
from service.battery import handle_step
from service.audio import handle_audio
from utils.command_util import send_set_device_config

logger = logging.getLogger(__name__)


class L16Device(BaseDevice):
    """
    L16设备控制器
    L16 Device Controller
    
    负责处理L16设备的所有数据和命令
    Responsible for handling all data and commands for L16 devices
    """
    
    def __init__(self, device_id: str):
        """
        初始化L16设备
        Initialize L16 device
        
        Args:
            device_id (str): 设备唯一标识符 / Device unique identifier
        """
        super().__init__(device_id)
        self.protocol = L16Protocol()
        self.data_models = L16DataModels()
        
        # 处理函数映射表 / Handler function mapping table
        self.handler_mapping = {
            "location": self._handle_location,
            "health": self._handle_health,
            "battery": self._handle_battery,
            "warning": self._handle_warning,
            "audio": self._handle_audio
        }
        
        self.logger.info(f"L16设备初始化完成 / L16 device initialization completed: {device_id}")
    
    def _get_device_type(self) -> str:
        """
        获取设备类型
        Get device type
        
        Returns:
            str: 设备类型 / Device type
        """
        return "L16"
    
    def get_supported_actions(self) -> List[str]:
        """
        获取设备支持的操作类型
        Get supported action types for the device
        
        Returns:
            List[str]: 支持的操作列表 / List of supported actions
        """
        return list(self.handler_mapping.keys())
    
    async def process_data(self, raw_data: Dict[str, Any]) -> Optional[Any]:
        """
        处理原始数据
        Process raw data
        
        Args:
            raw_data (Dict[str, Any]): 原始数据 / Raw data
            
        Returns:
            Optional[Any]: 处理结果 / Processing result
        """
        try:
            # 记录数据接收 / Log data reception
            action = raw_data.get("action", "unknown")
            await self.log_data_received(action, raw_data)
            
            # 协议解析 / Protocol parsing
            validated_data = await self.protocol.parse_request(raw_data)
            if not validated_data:
                return await self.protocol.format_error_response(400, "数据解析失败 / Data parsing failed")
            
            # 获取处理函数 / Get handler function
            handler = self.handler_mapping.get(action)
            if not handler:
                return await self.protocol.format_error_response(404, f"不支持的操作类型: {action} / Unsupported action type: {action}")
            
            # 执行处理逻辑 / Execute processing logic
            result = await handler(validated_data)
            
            # 格式化响应 / Format response
            return await self.protocol.format_response({"status": 1, "message": "处理成功 / Processing successful", "data": result})
            
        except Exception as e:
            await self.handle_error(e, f"处理数据时发生错误 / Error occurred while processing data: {action}")
            return await self.protocol.format_error_response(500, f"服务器内部错误 / Internal server error: {str(e)}")
    
    async def validate_data(self, data: Dict[str, Any]) -> bool:
        """
        验证数据有效性
        Validate data integrity
        
        Args:
            data (Dict[str, Any]): 待验证数据 / Data to validate
            
        Returns:
            bool: 验证结果 / Validation result
        """
        return await self.protocol.validate_request(data)
    
    async def send_command(self, command: Dict[str, Any]) -> Dict[str, Any]:
        """
        向设备发送命令
        Send command to device
        
        Args:
            command (Dict[str, Any]): 命令数据 / Command data
            
        Returns:
            Dict[str, Any]: 命令执行结果 / Command execution result
        """
        try:
            # 验证命令数据 / Validate command data
            if not isinstance(command, dict) or not command:
                raise ValueError("无效的命令数据 / Invalid command data")
            
            # 格式化命令请求 / Format command request
            formatted_command = await self.protocol.format_command_request(self.device_id, command)
            
            # 使用线程池执行同步操作，避免阻塞事件循环 / Use thread pool for sync operation to avoid blocking event loop
            result = await asyncio.to_thread(send_set_device_config, formatted_command)
            
            self.logger.info(f"命令发送完成 / Command sent: {self.device_id}")
            return {"status": 1, "message": "命令发送成功 / Command sent successfully", "result": result}
            
        except asyncio.TimeoutError:
            error_msg = "命令发送超时 / Command sending timeout"
            await self.handle_error(TimeoutError(error_msg), "发送命令时发生超时")
            return {"status": 0, "message": error_msg}
        except ValueError as e:
            await self.handle_error(e, "命令数据验证失败")
            return {"status": 0, "message": f"命令数据错误 / Command data error: {str(e)}"}
        except Exception as e:
            await self.handle_error(e, "发送命令时发生错误 / Error occurred while sending command")
            return {"status": 0, "message": f"命令发送失败 / Command sending failed: {str(e)}"}
    
    # 私有处理方法 / Private handler methods
    
    async def _handle_location(self, data) -> Any:
        """
        处理定位数据
        Handle location data
        
        Args:
            data: 定位数据模型 / Location data model
            
        Returns:
            Any: 处理结果 / Processing result
        """
        try:
            self.logger.info(f"处理定位数据 / Processing location data: {self.device_id}")
            
            # 验证定位数据有效性 / Validate location data validity
            if not hasattr(data, 'longitude') or not hasattr(data, 'latitude'):
                raise ValueError("缺少必要的定位字段 / Missing required location fields")
            
            if data.longitude is None or data.latitude is None:
                raise ValueError("定位坐标不能为空 / Location coordinates cannot be None")
            
            # 添加超时控制 / Add timeout control
            result = await asyncio.wait_for(
                location_handle_new(data), 
                timeout=30.0
            )
            
            # 更新位置元数据 / Update location metadata
            try:
                self.update_metadata("last_location", {
                    "longitude": float(data.longitude),
                    "latitude": float(data.latitude),
                    "timestamp": getattr(data, 'timestamp', None),
                    "processed_at": datetime.now().isoformat()
                })
            except Exception as meta_error:
                self.logger.warning(f"更新位置元数据失败 / Failed to update location metadata: {str(meta_error)}")
            
            return result
            
        except asyncio.TimeoutError:
            error_msg = f"定位数据处理超时 / Location data processing timeout: {self.device_id}"
            self.logger.error(error_msg)
            raise TimeoutError(error_msg)
        except ValueError as e:
            self.logger.error(f"定位数据验证失败 / Location data validation failed: {str(e)}")
            raise
        except Exception as e:
            self.logger.error(f"处理定位数据失败 / Location data processing failed: {str(e)}")
            raise
    
    async def _handle_health(self, data) -> Any:
        """
        处理健康数据
        Handle health data
        
        Args:
            data: 健康数据模型 / Health data model
            
        Returns:
            Any: 处理结果 / Processing result
        """
        try:
            self.logger.info(f"处理健康数据 / Processing health data: {self.device_id}")
            
            # 验证健康数据的基本有效性 / Validate basic health data validity
            if not hasattr(data, 'heart_rate') and not hasattr(data, 'blood_oxygen'):
                self.logger.warning("健康数据中缺少主要健康指标 / Missing main health indicators in health data")
            
            # 添加超时控制 / Add timeout control
            result = await asyncio.wait_for(
                handle_health(data), 
                timeout=45.0  # 健康数据处理可能需要更长时间
            )
            
            # 安全地更新健康状态元数据 / Safely update health status metadata
            try:
                health_metadata = {
                    "heart_rate": getattr(data, 'heart_rate', 0),
                    "blood_oxygen": getattr(data, 'blood_oxygen', 0),
                    "body_temperature": getattr(data, 'body_temperature', None),
                    "blood_pressure_high": getattr(data, 'blood_pressure_high', None),
                    "blood_pressure_low": getattr(data, 'blood_pressure_low', None),
                    "timestamp": getattr(data, 'timestamp', None),
                    "processed_at": datetime.now().isoformat()
                }
                
                # 移除None值以减少存储空间 / Remove None values to reduce storage space
                health_metadata = {k: v for k, v in health_metadata.items() if v is not None}
                
                self.update_metadata("last_health", health_metadata)
            except Exception as meta_error:
                self.logger.warning(f"更新健康元数据失败 / Failed to update health metadata: {str(meta_error)}")
            
            return result
            
        except asyncio.TimeoutError:
            error_msg = f"健康数据处理超时 / Health data processing timeout: {self.device_id}"
            self.logger.error(error_msg)
            raise TimeoutError(error_msg)
        except Exception as e:
            self.logger.error(f"处理健康数据失败 / Health data processing failed: {str(e)}")
            raise
    
    async def _handle_battery(self, data) -> Any:
        """
        处理电池和计步数据
        Handle battery and pedometer data
        
        Args:
            data: 电池数据模型 / Battery data model
            
        Returns:
            Any: 处理结果 / Processing result
        """
        try:
            self.logger.info(f"处理电池数据 / Processing battery data: {self.device_id}")
            
            # 验证电池数据有效性 / Validate battery data validity
            if not hasattr(data, 'battery') or not hasattr(data, 'pedometer'):
                raise ValueError("缺少必要的电池数据字段 / Missing required battery data fields")
            
            # 添加超时控制 / Add timeout control
            result = await asyncio.wait_for(
                handle_step(data), 
                timeout=30.0
            )
            
            # 安全地更新电池状态元数据 / Safely update battery status metadata
            try:
                battery_info = {
                    "battery_level": getattr(data, 'battery', 0),
                    "step_count": getattr(data, 'pedometer', 0),
                    "timestamp": getattr(data, 'timestamp', None),
                    "updated_at": datetime.now().isoformat()
                }
                
                self.update_metadata("battery_info", battery_info)
                
                # 保持向后兼容 / Maintain backward compatibility
                self.update_metadata("battery_level", battery_info["battery_level"])
                self.update_metadata("step_count", battery_info["step_count"])
                
            except Exception as meta_error:
                self.logger.warning(f"更新电池元数据失败 / Failed to update battery metadata: {str(meta_error)}")
            
            return result
            
        except asyncio.TimeoutError:
            error_msg = f"电池数据处理超时 / Battery data processing timeout: {self.device_id}"
            self.logger.error(error_msg)
            raise TimeoutError(error_msg)
        except ValueError as e:
            self.logger.error(f"电池数据验证失败 / Battery data validation failed: {str(e)}")
            raise
        except Exception as e:
            self.logger.error(f"处理电池数据失败 / Battery data processing failed: {str(e)}")
            raise
    
    async def _handle_warning(self, data) -> Any:
        """
        处理预警数据
        Handle warning data
        
        Args:
            data: 预警数据模型 / Warning data model
            
        Returns:
            Any: 处理结果 / Processing result
        """
        try:
            warning_type = getattr(data, 'type', 'unknown')
            self.logger.info(f"处理预警数据 / Processing warning data: {self.device_id}, 类型 / Type: {warning_type}")
            
            # 验证预警数据有效性 / Validate warning data validity
            if not hasattr(data, 'type'):
                raise ValueError("缺少预警类型字段 / Missing warning type field")
            
            # 添加超时控制 / Add timeout control
            result = await asyncio.wait_for(
                handle_warning(data), 
                timeout=30.0
            )
            
            # 安全地更新预警状态元数据 / Safely update warning status metadata
            try:
                warning_metadata = {
                    "type": warning_type,
                    "longitude": getattr(data, 'longitude', None),
                    "latitude": getattr(data, 'latitude', None),
                    "timestamp": getattr(data, 'timestamp', None),
                    "processed_at": datetime.now().isoformat()
                }
                
                # 移除None值 / Remove None values
                warning_metadata = {k: v for k, v in warning_metadata.items() if v is not None}
                
                self.update_metadata("last_warning", warning_metadata)
                
                # 统计预警次数 / Count warning occurrences
                warning_count = self.get_metadata("warning_count") or 0
                self.update_metadata("warning_count", warning_count + 1)
                
            except Exception as meta_error:
                self.logger.warning(f"更新预警元数据失败 / Failed to update warning metadata: {str(meta_error)}")
            
            return result
            
        except asyncio.TimeoutError:
            error_msg = f"预警数据处理超时 / Warning data processing timeout: {self.device_id}"
            self.logger.error(error_msg)
            raise TimeoutError(error_msg)
        except ValueError as e:
            self.logger.error(f"预警数据验证失败 / Warning data validation failed: {str(e)}")
            raise
        except Exception as e:
            self.logger.error(f"处理预警数据失败 / Warning data processing failed: {str(e)}")
            raise
    
    async def _handle_audio(self, data) -> Any:
        """
        处理音频数据
        Handle audio data
        
        Args:
            data: 音频数据模型 / Audio data model
            
        Returns:
            Any: 处理结果 / Processing result
        """
        try:
            self.logger.info(f"处理音频数据 / Processing audio data: {self.device_id}")
            
            # 验证音频数据有效性 / Validate audio data validity
            if not hasattr(data, 'audio') or not data.audio:
                raise ValueError("缺少音频数据字段 / Missing audio data field")
            
            if not hasattr(data.audio, 'voice') or not data.audio.voice:
                raise ValueError("缺少音频内容 / Missing audio content")
            
            # 添加超时控制（音频处理可能需要较长时间）/ Add timeout control (audio processing may take longer)
            result = await asyncio.wait_for(
                handle_audio(data), 
                timeout=60.0
            )
            
            # 安全地更新音频处理元数据 / Safely update audio processing metadata
            try:
                audio_metadata = {
                    "last_audio_processed": True,
                    "audio_length": len(data.audio.voice) if data.audio.voice else 0,
                    "timestamp": getattr(data, 'timestamp', None),
                    "processed_at": datetime.now().isoformat(),
                    "processing_result": str(result) if result else None
                }
                
                self.update_metadata("audio_info", audio_metadata)
                
                # 保持向后兼容 / Maintain backward compatibility
                self.update_metadata("last_audio_processed", True)
                
                # 统计音频处理次数 / Count audio processing occurrences
                audio_count = self.get_metadata("audio_count") or 0
                self.update_metadata("audio_count", audio_count + 1)
                
            except Exception as meta_error:
                self.logger.warning(f"更新音频元数据失败 / Failed to update audio metadata: {str(meta_error)}")
            
            return result
            
        except asyncio.TimeoutError:
            error_msg = f"音频数据处理超时 / Audio data processing timeout: {self.device_id}"
            self.logger.error(error_msg)
            raise TimeoutError(error_msg)
        except ValueError as e:
            self.logger.error(f"音频数据验证失败 / Audio data validation failed: {str(e)}")
            raise
        except Exception as e:
            self.logger.error(f"处理音频数据失败 / Audio data processing failed: {str(e)}")
            raise
    
    async def batch_send_command(self, imei_list: List[str], command: Dict[str, Any]) -> Dict[str, Any]:
        """
        批量发送命令
        Batch send command
        
        Args:
            imei_list (List[str]): 设备ID列表 / Device ID list
            command (Dict[str, Any]): 命令数据 / Command data
            
        Returns:
            Dict[str, Any]: 批量命令执行结果 / Batch command execution result
        """
        if not imei_list:
            return {"status": 0, "message": "设备列表为空 / Device list is empty", "results": []}
        
        if not isinstance(command, dict) or not command:
            return {"status": 0, "message": "无效的命令数据 / Invalid command data", "results": []}
        
        try:
            # 限制并发数量以避免资源耗尽 / Limit concurrency to avoid resource exhaustion
            semaphore = asyncio.Semaphore(10)  # 最多10个并发命令
            
            async def send_single_command(imei: str) -> Dict[str, Any]:
                async with semaphore:
                    try:
                        # 为每个设备格式化命令 / Format command for each device
                        device_command = await self.protocol.format_command_request(imei, command)
                        
                        # 使用线程池执行同步操作 / Use thread pool for sync operation
                        result = await asyncio.to_thread(send_set_device_config, device_command)
                        
                        return {
                            "imei": imei, 
                            "status": "success",
                            "result": result
                        }
                    except Exception as e:
                        self.logger.error(f"单个设备命令发送失败 / Single device command failed: {imei}, {str(e)}")
                        return {
                            "imei": imei,
                            "status": "failed",
                            "error": str(e)
                        }
            
            # 并发执行所有命令 / Execute all commands concurrently
            tasks = [send_single_command(imei) for imei in imei_list]
            results = await asyncio.gather(*tasks, return_exceptions=True)
            
            # 处理结果和异常 / Process results and exceptions
            processed_results = []
            successful_count = 0
            failed_count = 0
            
            for result in results:
                if isinstance(result, Exception):
                    failed_count += 1
                    processed_results.append({
                        "status": "failed",
                        "error": str(result)
                    })
                else:
                    if result.get("status") == "success":
                        successful_count += 1
                    else:
                        failed_count += 1
                    processed_results.append(result)
            
            self.logger.info(
                f"批量命令发送完成 / Batch command sending completed: "
                f"{len(imei_list)} devices, {successful_count} successful, {failed_count} failed"
            )
            
            return {
                "status": 1 if successful_count > 0 else 0,
                "message": f"批量命令完成 / Batch command completed: {successful_count}/{len(imei_list)} successful",
                "total": len(imei_list),
                "successful": successful_count,
                "failed": failed_count,
                "results": processed_results
            }
            
        except Exception as e:
            await self.handle_error(e, "批量发送命令时发生错误 / Error occurred while batch sending commands")
            return {
                "status": 0, 
                "message": f"批量命令发送失败 / Batch command sending failed: {str(e)}",
                "total": len(imei_list),
                "successful": 0,
                "failed": len(imei_list),
                "results": []
            }